module multi_obj_detect #(
    parameter 
        FRAME_LINE = 10'd640,
        FRAME_ROW  = 10'd480,
        MIN_DIST   = 10'd50
)(
    input                     clk                     ,
    input                     rst_n                   ,
    input                     pre_frame_vsync         ,
    input                     pre_frame_href          ,
    input                     pre_img_data_valid      ,
    input       [15:0]        pre_img_data            ,
    output      [655:0]       pre_target_pos              // 16组坐标
);

// 一维数组
reg  [40:0]  target_pos_out[15:0];
// lag 1 clk signal sync
reg per_frame_vsync_r;
reg pre_frame_href_r ;
reg per_frame_clken_r;
reg per_img_Bit_r    ;

wire per_img_Bit;

// 一维数组转线网输出
generate
    genvar t;
    for (t = 0;t < 16 ;t = t + 1) begin :gen_target_pos
        assign pre_target_pos[(40 + t * 41) : (t * 41)] = target_pos_out[t];
    end
endgenerate

assign per_img_Bit = (pre_img_data != 16'd0) ? 1'd1 : 1'd0;

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
        per_frame_vsync_r <= 1'd0;
        pre_frame_href_r  <= 1'd0;
        per_frame_clken_r <= 1'd0;
        per_img_Bit_r     <= 1'd0;
    end
    else begin
        per_frame_vsync_r <= pre_frame_vsync;
        pre_frame_href_r  <= pre_frame_href;
        per_frame_clken_r <= pre_img_data_valid;
        per_img_Bit_r     <= per_img_Bit;
    end
end

wire vsync_pos_flag;
wire vsync_neg_flag;
assign vsync_pos_flag = pre_frame_vsync & (~per_frame_vsync_r);
assign vsync_pos_flag = (~pre_frame_vsync) & per_frame_vsync_r;

// 行列计数
reg [9:0] x_cnt; // line_cnt
reg [9:0] y_cnt; // row_cnt
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
        x_cnt <= 10'd0;
        y_cnt <= 10'd0;
    end
    else if(pre_frame_vsync)begin
        x_cnt <= 10'd0;
        y_cnt <= 10'd0;
    end
    else if(pre_img_data_valid)begin
        if(x_cnt < FRAME_LINE - 1)begin
            x_cnt <= x_cnt + 10'd1;
            y_cnt <= y_cnt;
        end
        else begin
            x_cnt <= 10'd0;
            y_cnt <= y_cnt + 10'd1;
        end
    end
    else ;
end

// 寄存坐标
reg [9:0] x_cnt_r;
reg [9:0] y_cnt_r;
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
        x_cnt_r <= 10'd0;
        y_cnt_r <= 10'd0;
    end
    else begin
        x_cnt_r <= x_cnt;
        y_cnt_r <= y_cnt;
    end
end

reg [40:0] target_pos             [15:0]; // 边界

wire [15:0] target_flag                 ; // 有效值
wire [ 9:0] target_left           [15:0]; // 上下左右
wire [ 9:0] target_right          [15:0];
wire [ 9:0] target_top            [15:0];
wire [ 9:0] target_bottom         [15:0];

wire [ 9:0] target_boarder_left   [15:0];
wire [ 9:0] target_boarder_right  [15:0];
wire [ 9:0] target_boarder_top    [15:0];
wire [ 9:0] target_boarder_bottom [15:0];

generate
    genvar i;
    for (i = 0; i < 15 ; i = i + 1) begin
        assign target_flag  [i] = target_pos[i][40];

        assign target_left  [i] = (target_pos[i][39:30] < FRAME_ROW - 1 - MIN_DIST  ) ? (target_pos[i][39:30] + MIN_DIST) : FRAME_ROW;
        assign target_right [i] = (target_pos[i][29:20] < FRAME_LINE - 1 - MIN_DIST ) ? (target_pos[i][29:20] + MIN_DIST) : FRAME_LINE;
        assign target_top   [i] = (target_pos[i][19:10] > 10'd0 + MIN_DIST          ) ? (target_pos[i][19:10] - MIN_DIST) : 10'd0;
        assign target_bottom[i] = (target_pos[i][ 9: 0] > 10'd0 + MIN_DIST          ) ? (target_pos[i][ 9: 0] - MIN_DIST) : 10'd0;

        assign target_boarder_left  [i] = target_pos[i][39:30];
        assign target_boarder_right [i] = target_pos[i][29:20];
        assign target_boarder_top   [i] = target_pos[i][19:10];
        assign target_boarder_bottom[i] = target_pos[i][ 9: 0];
    end
endgenerate

// 检测并标记目标
integer j;
reg [ 3:0] target_cnt;
reg [15:0] new_target_flag;

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
        for (j = 0; j < 16; j = j + 1) begin
            target_pos[j] <= 41'd0;
        end
        new_target_flag <= 16'd0;
        target_cnt <= 4'd0;
    end
    else if(vsync_neg_flag)begin
        for (j = 0; j < 16; j = j + 1) begin
            target_pos[j] <= 41'd0;
        end
        new_target_flag <= 16'd0;
        target_cnt <= 4'd0;
    end
    else begin
        // the 1 clk
        if(pre_img_data_valid && per_img_Bit) begin
            for (j = 0; j < 16; j = j + 1) begin
                if(target_flag[j] == 1'd0)
                    new_target_flag[j] <= 1'd1;
                else begin
                    if((x_cnt < target_left[j]) || (x_cnt > target_right[j]) || (y_cnt < target_top[j]) || (y_cnt > target_bottom[j]))
                        new_target_flag[j] <= 1'd1;
                    else
                        new_target_flag[j] <= 1'd0;
                end
            end
        end
        else
            new_target_flag <= 16'd0;

        // the 2 clk
        if(per_frame_clken_r && per_img_Bit_r)begin
            if(new_target_flag == 16'hffff)begin
                target_pos[target_cnt] <= {1'b1, y_cnt_r, x_cnt_r, y_cnt_r, x_cnt_r};
                target_cnt <= target_cnt + 1'd1;
            end
            else if(new_target_flag > 16'd0)begin
                for (j = 0; j < 16; j = j + 1) begin
                    target_pos[j][40] <= 1'd1;
                    if(x_cnt_r < target_pos[j][9:0]) // x最大值
                        target_pos[j][9:0] <= x_cnt_r;
                    else;

                    if(x_cnt_r > target_pos[j][29:20]) // x最小值
                        target_pos[j][29:20] <= x_cnt_r;
                    else;

                    if(y_cnt_r < target_pos[j][19:10]) // y最大值
                        target_pos[j][19:10] <= y_cnt_r;
                    else;

                    if(y_cnt_r > target_pos[j][39:30]) // y最小值
                        target_pos[j][39:30] <= y_cnt_r;
                    else;
                end
            end
        end
    end
end

// 寄存输出
integer k;

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
        for (k = 0; k < 16; k = k + 1)
            target_pos_out[k] <= 41'd0;
    end
    else if(vsync_pos_flag)begin
        for (k = 0; k < 16; k = k + 1)
            target_pos_out[k] <= target_pos[k];
    end
    else ;
end
endmodule